#!/usr/bin/env python3
import serial
import time
import os
import sys
import argparse

def uart_loopback_continuous_test(port, baudrate=9600, duration=30):
    """
    循环发送 UART 测试
    :param port: 串口设备
    :param baudrate: 波特率
    :param duration: 测试持续时间（秒）
    """
    print(f"开始循环 UART 测试 - 端口: {port}, 波特率: {baudrate}")
    print(f"测试将持续 {duration} 秒")
    print("按 Ctrl+C 停止测试")
    print("-" * 50)
    
    # 检查设备是否存在
    if not os.path.exists(port):
        print(f"错误: 设备 {port} 不存在!")
        return False
    
    try:
        # 配置串口
        ser = serial.Serial(
            port=port,
            baudrate=baudrate,
            bytesize=serial.EIGHTBITS,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            timeout=1.0,
            write_timeout=1.0
        )
        
        start_time = time.time()
        packet_count = 0
        success_count = 0
        
        while time.time() - start_time < duration:
            try:
                # 清空缓冲区
                ser.reset_input_buffer()
                ser.reset_output_buffer()
                time.sleep(0.05)
                
                # 生成测试数据（包含时间戳和序号）
                timestamp = time.strftime("%H:%M:%S")
                test_data = f"UART Test [{timestamp}] Packet: {packet_count:04d} ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
                
                # 发送数据
                ser.write(test_data.encode())
                ser.flush()
                
                print(f"[TX #{packet_count:04d}] {test_data}")
                
                # 接收数据
                received_data = ""
                max_retry = 3
                
                for retry in range(max_retry):
                    time.sleep(0.1)  # 等待数据回传
                    if ser.in_waiting > 0:
                        received_bytes = ser.read(ser.in_waiting)
                        received_data = received_bytes.decode('utf-8', errors='ignore')
                        break
                    elif retry == max_retry - 1:
                        print("  ⚠️  未接收到数据")
                
                # 验证结果
                if received_data:
                    if received_data == test_data:
                        print(f"  ✅ [RX #{packet_count:04d}] 数据匹配成功")
                        success_count += 1
                    else:
                        print(f"  ❌ [RX #{packet_count:04d}] 数据不匹配")
                        print(f"     期望: {test_data}")
                        print(f"     实际: {received_data}")
                else:
                    print(f"  ❌ [RX #{packet_count:04d}] 未接收到任何数据")
                
                packet_count += 1
                
                # 每秒发送2-3个数据包，避免太快
                time.sleep(2)
                
            except KeyboardInterrupt:
                print("\n用户中断测试")
                break
            except Exception as e:
                print(f"  🔴 数据包 #{packet_count} 错误: {e}")
                packet_count += 1
                time.sleep(1)  # 出错后等待1秒
        
        # 测试统计
        elapsed_time = time.time() - start_time
        print("-" * 50)
        print("测试统计:")
        print(f"总运行时间: {elapsed_time:.2f} 秒")
        print(f"总发送数据包: {packet_count} 个")
        print(f"成功接收数据包: {success_count} 个")
        
        if packet_count > 0:
            success_rate = (success_count / packet_count) * 100
            print(f"成功率: {success_rate:.2f}%")
        
        ser.close()
        return success_count > 0
        
    except Exception as e:
        print(f"串口初始化错误: {e}")
        return False

def uart_simple_continuous_tx(port, baudrate=9600):
    """
    简单循环发送（只发送不接收）
    """
    print(f"开始简单循环发送测试 - 端口: {port}")
    print("按 Ctrl+C 停止")
    
    if not os.path.exists(port):
        print(f"错误: 设备 {port} 不存在!")
        return
    
    try:
        ser = serial.Serial(port, baudrate, timeout=1)
        count = 0
        
        while True:
            try:
                # 简单的测试数据
                message = f"Continuous Test {count:06d}\r\n"
                ser.write(message.encode())
                # ser.flush()
                
                print(f"发送: {message.strip()}")
                count += 1
                time.sleep(1)  # 每秒发送一次
                
            except KeyboardInterrupt:
                print(f"\n停止测试，共发送 {count} 条消息")
                break
            except Exception as e:
                print(f"发送错误: {e}")
                time.sleep(1)
        
        ser.close()
        
    except Exception as e:
        print(f"错误: {e}")

def list_serial_ports():
    """列出所有可用的串口设备"""
    print("可用的串口设备:")
    print("-" * 30)
    
    # 常见的串口设备模式
    port_patterns = ['ttyS', 'ttyUSB', 'ttyACM', 'ttyAMA', 'ttyO']
    found_ports = []
    
    for pattern in port_patterns:
        ports = [f for f in os.listdir('/dev') if f.startswith(pattern)]
        for port in sorted(ports):
            port_path = f"/dev/{port}"
            if os.path.exists(port_path):
                found_ports.append(port_path)
    
    if found_ports:
        for port in sorted(found_ports):
            print(f"  {port}")
    else:
        print("  未找到串口设备")
    
    print("-" * 30)
    return found_ports

def main():
    parser = argparse.ArgumentParser(description='UART 串口测试工具')
    parser.add_argument('port', nargs='?', help='串口设备路径 (例如: /dev/ttyS3, /dev/ttyUSB0)')
    parser.add_argument('-b', '--baudrate', type=int, default=9600, 
                       help='波特率 (默认: 9600)')
    parser.add_argument('-m', '--mode', choices=['loopback', 'txonly'], default='loopback',
                       help='测试模式: loopback(回环测试), txonly(只发送) (默认: loopback)')
    parser.add_argument('-d', '--duration', type=int, default=30,
                       help='测试持续时间(秒) (默认: 30)')
    parser.add_argument('-l', '--list-ports', action='store_true',
                       help='列出可用的串口设备')
    
    args = parser.parse_args()
    
    # 列出可用串口
    if args.list_ports:
        list_serial_ports()
        return
    
    # 如果没有提供端口参数，显示错误信息
    if args.port is None:
        print("错误: 必须提供串口设备路径")
        print("\n用法示例:")
        print("  python3 uart.py /dev/ttyS3                    # 基本用法")
        print("  python3 uart.py /dev/ttyUSB0 -b 115200        # 指定波特率")
        print("  python3 uart.py /dev/ttyS3 -m txonly          # 只发送模式")
        print("  python3 uart.py -l                            # 列出可用串口")
        print("\n使用 -l 参数查看可用的串口设备:")
        list_serial_ports()
        return
    
    # 检查端口是否存在
    if not os.path.exists(args.port):
        print(f"错误: 串口设备 {args.port} 不存在!")
        print("使用 -l 参数查看可用的串口设备:")
        list_serial_ports()
        return
    
    print(f"使用串口: {args.port}")
    print(f"波特率: {args.baudrate}")
    
    if args.mode == 'loopback':
        print("模式: 回环测试")
        uart_loopback_continuous_test(args.port, args.baudrate, args.duration)
    else:
        print("模式: 只发送")
        uart_simple_continuous_tx(args.port, args.baudrate)

if __name__ == "__main__":
    main()